import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//反射: 在运行状态中, 对于任意一个类, 都能够知道这个类的所有属性和方法
public class Reflection {
    //Class类: 代表类的实体, 在运行的Java应用程序中表示类和接口
    public void ReflectionClass() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class<?> classStudent = null;
        //根据类名返回类的对象
        classStudent = Class.forName("Student");
        //返回一个数组, 数组中包含该类中所有类和接口类的对象
        Class<?>[] studentClassArray = classStudent.getDeclaredClasses();
        //getClassLoader()获得类的加载器
        classStudent.getClassLoader();
        //创建类的实例
        Student student = (Student) classStudent.newInstance();
        System.out.println(student);
        //获得类的完整路径名字
        String path = classStudent.getName();
        System.out.println(path);
    }

    public void ReflectionConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?>  classStudent = Student.class;
        //getConstructor(Class...<?> parameterTypes) 获得该类中与参数类型匹配的公有构造方法
        Constructor<?> constructor1 = classStudent.getConstructor();
        //getConstructors() 获得所有公用构造方法
        Constructor<?>[] constructor2 = classStudent.getConstructors();
        //getDeclaredConstructor(Class...<?> parameterTypes) 获得该类中与参数匹配的构造方法
        Constructor<?> constructor3 = classStudent.getDeclaredConstructor(String.class, int.class);
        constructor3.setAccessible(true);//私有的构造, 需要设置权限
        System.out.println((Student) constructor3.newInstance("xiaoming", 15));
        //获得该类所有构造方法
        Constructor<?>[] constructor4 = classStudent.getDeclaredConstructors();
    }

    public void ReflectionField() throws NoSuchFieldException, IllegalAccessException {
        Student student = new Student();
        Class<?> classStudent = student.getClass();
        //getField() 获得公有的属性对象
        Field field1 = classStudent.getField("age");
        //getFields() 获得所有公有的属性对象
        Field[] field2 = classStudent.getFields();
        //getDeclaredField() 获得某个属性对象
        Field field3 = classStudent.getDeclaredField("name");
        field3.setAccessible(true);
        field3.set(student,"caocao");
        System.out.println(student);
        //getDeclaredFields() 获得所有属性对象
        Field[] fields4 = classStudent.getDeclaredFields();
    }
    public void ReflectionMethod() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Class<?> classStudent = Class.forName("Student");
        //getMethod() 获得该类某个公有方法
        Method method1 = classStudent.getMethod("sleep");
        //getMethods() 获得该类所有公有方法
        Method[] method2 = classStudent.getMethods();
        //getDeclaredMethod() 获得该类某个方法
        Method method3 = classStudent.getDeclaredMethod("function", String.class);
        Object student = classStudent.newInstance();
        method3.setAccessible(true);
        method3.invoke(student,"我是反射参数");
        //getDeclaredMethods() 获得该类所有方法
        Method[] method4 = classStudent.getDeclaredMethods();
    }
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {
        Reflection reflection = new Reflection();
        reflection.ReflectionClass();
        reflection.ReflectionConstructor();
        reflection.ReflectionField();
        reflection.ReflectionMethod();
    }
}

class Student {
    //私有属性name
    private String name = "bit";
    //公有属性age
    public int age = 18;
    //不带参数的构造方法
    public Student(){
        System.out.println("Student()");
    }

    private Student(String name,int age) {
        this.name = name;
        this.age = age;
        System.out.println("Student(String,name)");
    }

    private void eat(){
        System.out.println("i am eat");
    }

    public void sleep(){
        System.out.println("i am pig");
    }

    private void function(String str) {
        System.out.println(str);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}